package dex

import (
	"bytes"
	"encoding/binary"
	"errors"
)

// NoIndex 偏移过长
var NoIndex = 0xFFFFFFFF

// Reader Dex的数据块+偏移
type Reader struct {
	data []byte
	pos  int
}

// 读的时候，会自动修改指针位置
func (s *Reader) Read(size int) ([]byte, error) {
	if !(size < len(s.data)-s.pos) {
		return nil, errors.New("读取数据超过数据长度")
	}
	result := s.data[s.pos : s.pos+size]
	s.pos += size
	return result, nil
}

// flag 如果为真则使用Read，如果为false则使用Seek

// U8 read 1 bytes FF
func (s *Reader) U8(flag bool) int32 {
	var result int32
	bs, _ := s.Read(1)
	binary.Read(bytes.NewReader(bs), binary.LittleEndian, &result)
	return result
}

// U16 read 2 bytes FF FF
func (s *Reader) U16() uint16 {
	bs, _ := s.Read(2)
	return binary.LittleEndian.Uint16(bs)
}

// U32 read 4 bytes FF FF FF FF
func (s *Reader) U32() uint32 {
	bs, _ := s.Read(4)
	return binary.LittleEndian.Uint32(bs)
}

// U64 read 8 bytes FF FF FF FF FF FF FF FF
func (s *Reader) U64() uint64 {
	bs, _ := s.Read(8)
	return binary.LittleEndian.Uint64(bs)

}

// Uleb128 读一个uleb128格式的字符串
func (s *Reader) Uleb128() uint64 {
	var result uint64
	var shift uint
	for {
		b := s.data[s.pos]
		result |= (uint64(0x7F & b)) << shift
		if b&0x80 == 0 {
			break
		}
		shift += 7
		s.pos++
	}
	s.pos++
	return result
}

// ReadCStr 读取ASCII字符串
func (s *Reader) ReadCStr(off int) string {
	return string(s.data[s.pos : s.pos+off])
}

// SizeOff 一块数据，表示目标数据的大小和偏移
type SizeOff struct {
	size int
	off  int
}

func (s *Reader) readSizeOff() SizeOff {
	return SizeOff{
		size: int(s.U32()),
		off:  int(s.U32()),
	}
}

// // Seek 从指定的偏移位置读取，指定大小的数据（读数据的时候，不修改位置）
// func (s *Reader) Seek(offset int, size int) ([]byte, error) {
// 	if size <= 0 {
// 		return nil, errors.New("数据长度小于或等于零")
// 	}
// 	if !(size < len(s.data)-offset) {
// 		return nil, errors.New("读取数据超过数据长度")
// 	}
// 	bytes := s.data[offset : offset+size]
// 	return bytes, nil
// }

// // Get 1 bytes FF
// func (s *Reader) GetU8(offset int) int32 {
// 	var result int32
// 	bs, _ := s.Seek(offset, 1)
// 	binary.Read(bytes.NewReader(bs), binary.LittleEndian, &result)
// 	return result
// }

// // Get 2 bytes FF FF
// func (s *Reader) GetU16(offset int) int32 {
// 	var result int32
// 	bs, _ := s.Seek(offset, 2)
// 	binary.Read(bytes.NewReader(bs), binary.LittleEndian, &result)
// 	return result
// }

// // Get 4 bytes FF FF FF FF
// func (s *Reader) GetU32(offset int) int {
// 	var result int32
// 	bs, _ := s.Seek(offset, 4)
// 	binary.Read(bytes.NewReader(bs), binary.LittleEndian, &result)

// 	return int(result)
// }

// // Get Uleb128
// func (s *Reader) GetUleb128(offset int) uint64 {
// 	var result uint64
// 	var shift uint
// 	for {
// 		b := s.data[offset]
// 		result |= (uint64(0x7F & b)) << shift
// 		if b&0x80 == 0 {
// 			break
// 		}
// 		shift += 7
// 		offset++
// 	}
// 	offset++
// 	return result
// }

// // GetCStr 读取字符串
// func (s *Reader) GetCStr(start int, off int) string {
// 	return string(s.data[start : start+off])
// }
